home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_jnos / j109lxa4.tgz / j109lxa4.tar / trace.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  13KB  |  565 lines

  1. /* Packet tracing - top level and generic routines, including hex/ascii
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by G1EMM
  5.  *
  6.  * Tracing to session taken from WNOS3, by Johan. K. Reinalda, WG7J
  7.  * "Monitor" mode added by Brandon S. Allbery, KF8NH
  8.  */
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #include <time.h>
  12. #include "global.h"
  13. #include "config.h"
  14. #ifdef ANSIPROTO
  15. #include <stdarg.h>
  16. #endif
  17. #include "mbuf.h"
  18. #include "iface.h"
  19. #include "pktdrvr.h"
  20. #include "commands.h"
  21. #include "session.h"
  22. #include "trace.h"
  23. #include "cmdparse.h"
  24.  
  25. #ifdef TRACE
  26. #ifdef MONITOR
  27. static void monitor_dump __ARGS((FILE *fp, struct mbuf **bpp));
  28. #endif
  29. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  30. static void ctohex __ARGS((char *buf,int16 c));
  31. static void fmtline __ARGS((FILE *fp,int16 addr,char *buf,int16 len));
  32. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  33. static void showtrace __ARGS((struct iface *ifp));
  34. extern struct session *Current;
  35. extern struct session *Command;
  36. #ifdef MULTITASK
  37. extern int Nokeys;
  38. #endif
  39.  
  40. extern int Tracesession;
  41. extern struct session *Trace;
  42.  
  43. #ifdef MONITOR
  44.  
  45. #include "slip.h"
  46.  
  47. static char *
  48. #ifdef PROTOTYPES
  49. kissname(struct iface *ifp, struct mbuf *bp, unsigned type)
  50. #else
  51. kissname(ifp, bp, type)
  52.     struct iface *ifp;
  53.     struct mbuf *bp;
  54.     unsigned type;
  55. #endif
  56. {
  57.     int port;
  58.  
  59.     if (ifp->type != CL_AX25 || type != CL_KISS)
  60.     return ifp->name;
  61.     port = (bp->data[0] & 0xF0) >> 4;
  62.     if (Slip[ifp->xdev].kiss[port] == NULLIF)
  63.     return ifp->name;
  64.     return Slip[ifp->xdev].kiss[port]->name;
  65. }
  66.  
  67. #endif
  68.  
  69. int
  70. dostrace(argc,argv,p)
  71. int argc;
  72. char *argv[];
  73. void *p;
  74. {
  75.     if(Trace == NULLSESSION)
  76.     argc = 0; /* No session setup, so don't allow turning it on ! */
  77.     return setbool(&Tracesession,"Trace to session",argc,argv);
  78. }
  79.  
  80. /* Redefined here so that programs calling dump in the library won't pull
  81.  * in the rest of the package
  82.  */
  83.  
  84. static char nospace[] = "No space!!\n";
  85.  
  86. struct tracecmd Tracecmd[] = {
  87.     "input",        IF_TRACE_IN,    IF_TRACE_IN,
  88.     "-input",       0,              IF_TRACE_IN,
  89.     "output",       IF_TRACE_OUT,   IF_TRACE_OUT,
  90.     "-output",      0,              IF_TRACE_OUT,
  91.     "broadcast",    0,              IF_TRACE_NOBC,
  92.     "-broadcast",   IF_TRACE_NOBC,  IF_TRACE_NOBC,
  93.     "raw",          IF_TRACE_RAW,   IF_TRACE_RAW,
  94.     "-raw",         0,              IF_TRACE_RAW,
  95.     "ascii",        IF_TRACE_ASCII, IF_TRACE_ASCII|IF_TRACE_HEX,
  96.     "-ascii",       0,              IF_TRACE_ASCII|IF_TRACE_HEX,
  97.     "hex",          IF_TRACE_HEX,   IF_TRACE_ASCII|IF_TRACE_HEX,
  98.     "-hex",         IF_TRACE_ASCII, IF_TRACE_ASCII|IF_TRACE_HEX,
  99. #ifdef MONITOR
  100. /* borrow a meaningless combination for the new trace type */
  101. #define IF_MONITOR (IF_TRACE_ASCII|IF_TRACE_HEX)
  102.     "monitor",    IF_MONITOR,    IF_TRACE_ASCII|IF_TRACE_HEX,
  103.     "-monitor",    IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX,
  104. #endif
  105.     "off",          0,              0xffff,
  106.     NULLCHAR,       0,              0
  107. };
  108.  
  109. void
  110. dump(ifp,direction,type,bp)
  111. register struct iface *ifp;
  112. int direction;
  113. unsigned type;
  114. struct mbuf *bp;
  115. {
  116.     struct mbuf *tbp;
  117.     void (*func) __ARGS((FILE *,struct mbuf **,int,int));
  118.     int16 size;
  119.     time_t timer;
  120.     char *cp;
  121.  
  122.     if(ifp == NULL || (ifp->trace & direction) == 0)
  123.     return; /* Nothing to trace */
  124.  
  125. #ifdef UNIX
  126.     /* need to check if the traced-to session is a "blocking" session */
  127.     if (sm_blocked(Tracesession? Trace: Command))
  128.         return;
  129. #else
  130.     if(Tracesession) {
  131.     /* Disable trace if this is not Trace-sessions,
  132.      * or when shelled out, and not tracing to file */
  133. #ifdef MULTITASK
  134.     if((Current != Trace || Nokeys) && (ifp->trfp == stdout))
  135. #else
  136.     if((Current != Trace) && (ifp->trfp == stdout))
  137. #endif /* MULTITASK */
  138.         return; /* Nothing to trace */
  139.     } else {
  140.     /* Disable trace on non-command sessions or when shelled out */
  141. #ifdef MULTITASK
  142.     if((Current != Command || Nokeys) && (ifp->trfp == stdout))
  143. #else
  144.     if((Current != Command) && (ifp->trfp == stdout))
  145. #endif
  146.         return; /* Nothing to trace */
  147.     }
  148. #endif
  149.  
  150.     switch(direction){
  151.     case IF_TRACE_IN:
  152.         if((ifp->trace & IF_TRACE_NOBC)
  153.          && (Tracef[type].addrtest != NULLFP((struct iface*,struct mbuf*)))
  154.          && (*Tracef[type].addrtest)(ifp,bp) == 0)
  155.             return;         /* broadcasts are suppressed */
  156.         time(&timer);
  157.         cp = ctime(&timer);
  158.         cp[24] = '\0';
  159. #ifdef MONITOR
  160.         if ((ifp->trace & IF_MONITOR) == IF_MONITOR)
  161.             fprintf(ifp->trfp, "(%s) ", kissname(ifp, bp, type));
  162.         else
  163. #endif
  164.         fprintf(ifp->trfp,"\n%s - %s recv:\n",cp,ifp->name);
  165.         break;
  166.     case IF_TRACE_OUT:
  167.         time(&timer);
  168.         cp = ctime(&timer);
  169.         cp[24] = '\0';
  170. #ifdef MONITOR
  171.         if ((ifp->trace & IF_MONITOR) == IF_MONITOR)
  172.             fprintf(ifp->trfp, "(%s) ", kissname(ifp, bp, type));
  173.         else
  174. #endif
  175.         fprintf(ifp->trfp,"\n%s - %s sent:\n",cp,ifp->name);
  176.         break;
  177.     }
  178.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  179.         fprintf(ifp->trfp,"empty packet!!\n");
  180.         return;
  181.     }
  182.  
  183.     if(type < NCLASS)
  184.         func = Tracef[type].tracef;
  185.     else
  186. #ifdef MONITOR
  187.         func = NULLVFP((FILE*,struct mbuf**,int,int));
  188. #else
  189.         func = NULLVFP((FILE *,struct mbuf**,int));
  190. #endif
  191.  
  192.     dup_p(&tbp,bp,0,size);
  193.     if(tbp == NULLBUF){
  194.         fprintf(ifp->trfp,nospace);
  195.         return;
  196.     }
  197.  
  198. #ifdef MONITOR
  199.     if(func != NULLVFP((FILE*,struct mbuf**,int,int)))
  200.         (*func)(ifp->trfp,&tbp,1,((ifp->trace&IF_MONITOR) == IF_MONITOR));
  201.     if ((ifp->trace & IF_MONITOR) == IF_MONITOR)
  202.         monitor_dump(ifp->trfp, &tbp);
  203.     else
  204. #else
  205.     if(func != NULLVFP((FILE*,struct mbuf**,int)))
  206.         (*func)(ifp->trfp,&tbp,1);
  207. #endif
  208.     if(ifp->trace & IF_TRACE_ASCII){
  209.         /* Dump only data portion of packet in ascii */
  210.         ascii_dump(ifp->trfp,&tbp);
  211.     } else if(ifp->trace & IF_TRACE_HEX){
  212.         /* Dump entire packet in hex/ascii */
  213.         free_p(tbp);
  214.         dup_p(&tbp,bp,0,len_p(bp));
  215.         if(tbp != NULLBUF)
  216.             hex_dump(ifp->trfp,&tbp);
  217.         else
  218.             fprintf(ifp->trfp,nospace);
  219.     }
  220.     free_p(tbp);
  221. }
  222.  
  223. /* Dump packet bytes, no interpretation */
  224. void
  225. raw_dump(ifp,direction,bp)
  226. struct iface *ifp;
  227. int direction;
  228. struct mbuf *bp;
  229. {
  230.     struct mbuf *tbp;
  231.  
  232.     /* Dump entire packet in hex/ascii */
  233.     fprintf(ifp->trfp,"\n******* raw packet dump (%s %s)\n",
  234.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),ifp->name);
  235.     dup_p(&tbp,bp,0,len_p(bp));
  236.     if(tbp != NULLBUF)
  237.         hex_dump(ifp->trfp,&tbp);
  238.     else
  239.         fprintf(ifp->trfp,nospace);
  240.     fprintf(ifp->trfp,"*******\n");
  241.     free_p(tbp);
  242.     return;
  243. }
  244.  
  245. /* Dump an mbuf in hex */
  246. static void
  247. hex_dump(fp,bpp)
  248. FILE *fp;
  249. register struct mbuf **bpp;
  250. {
  251.     int16 n;
  252.     int16 address;
  253.     char buf[16];
  254.  
  255.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  256.         return;
  257.  
  258.     address = 0;
  259.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  260.         fmtline(fp,address,buf,n);
  261.         address += n;
  262.     }
  263. }
  264. /* Dump an mbuf in ascii */
  265. static void
  266. ascii_dump(fp,bpp)
  267. FILE *fp;
  268. register struct mbuf **bpp;
  269. {
  270.     int c;
  271.     register int16 tot;
  272.  
  273.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  274.         return;
  275.  
  276.     tot = 0;
  277.     while((c = PULLCHAR(bpp)) != -1){
  278.         if((tot % 64) == 0)
  279.             fprintf(fp,"%04x  ",tot);
  280.         fprintf(fp,"%c",(isprint(uchar(c)) ? c : '.'));
  281.         if((++tot % 64) == 0)
  282.             fprintf(fp,"\n");
  283.     }
  284.     if((tot % 64) != 0)
  285.         fprintf(fp,"\n");
  286. }
  287. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  288.  * translation, e.g.,
  289.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  290.  */
  291. static void
  292. fmtline(fp,addr,buf,len)
  293. FILE *fp;
  294. int16 addr;
  295. char *buf;
  296. int16 len;
  297. {
  298.     char line[80];
  299.     register char *aptr,*cptr;
  300.     register char c;
  301.  
  302.     memset(line,' ',sizeof(line));
  303.     ctohex(line,(int16)hibyte(addr));
  304.     ctohex(line+2,(int16)lobyte(addr));
  305.     aptr = &line[6];
  306.     cptr = &line[55];
  307.     while(len-- != 0){
  308.         c = *buf++;
  309.         ctohex(aptr,(int16)uchar(c));
  310.         aptr += 3;
  311.         c &= 0x7f;
  312.         *cptr++ = isprint(uchar(c)) ? c : '.';
  313.     }
  314.     *cptr++ = '\n';
  315.     fprintf(fp,"%.*s",(unsigned)(cptr-line),line);
  316. }
  317. /* Convert byte to two ascii-hex characters */
  318. static void
  319. ctohex(buf,c)
  320. register char *buf;
  321. register int16 c;
  322. {
  323.     static char hex[] = "0123456789abcdef";
  324.  
  325.     *buf++ = hex[hinibble(c)];
  326.     *buf = hex[lonibble(c)];
  327. }
  328.  
  329. #ifdef MONITOR
  330. /* Dump an mbuf in ascii with newlines but no others. */
  331. /* (limited ANSI parsing, since that seems popular here) */
  332. static void
  333. monitor_dump(fp,bpp)
  334. FILE *fp;
  335. register struct mbuf **bpp;
  336. {
  337.     struct mbuf *tmp;
  338.     int c, esc, nl;
  339.  
  340.     if (bpp == NULLBUFP || *bpp == NULLBUF)
  341.         return;
  342.  
  343.     /* check for lots of non-ASCII, non-ANSI and ascii_dump instead */
  344.     dup_p(&tmp, *bpp, 0, len_p(*bpp));
  345.     nl = 0;
  346.     while ((c = PULLCHAR(&tmp)) != -1)
  347.     {
  348.         /*
  349.          * Printable characters are okay, as are \n \t \r \b \f \a \E
  350.          * Nulls and other control characters are verboten, as are meta
  351.          * controls.  Meta-printables are accepted, since they may be
  352.          * intended as PC graphics (but don't expect them to dump right
  353.          * from here because I don't decode them.  Maybe someday).
  354.          * (also pass 0xff - FBB "Mail for:" beacons include it???)
  355.          */
  356.         if (c < 7 || (c > 13 && c < 27) || (c > 27 && c < 32) ||
  357.             (c > 126 && c < 174) || (c > 223 && c < 255))
  358.             nl = 1;
  359.     }
  360.     if (nl)
  361.     {
  362.         ascii_dump(fp, bpp);
  363.         return;
  364.     }
  365.     esc = 0;
  366.     nl = 1;
  367.     while ((c = PULLCHAR(bpp)) != -1)
  368.     {
  369.         if (c == 0x1B)
  370.             esc = !esc;
  371.         else if (esc == 1 && c == '[')
  372.             esc = 2;
  373.         else if (esc == 1)
  374.             esc = 0;
  375.         else if (esc == 2 && c != ';' && !isdigit(c))
  376.         {
  377.             /* handle some common cases? */
  378.             esc = 0;
  379.         }
  380.         else if (esc == 0 && c == '\r')
  381.         {
  382.             fprintf(fp, "\n");
  383.             nl = 1;
  384.         }
  385.         /* safe programming: not everyone *always* agrees on isprint */
  386.         else if (esc == 0 && c != '\n' && (isprint(c) || c == '\t'))
  387.         {
  388.             fprintf(fp, "%c", c);
  389.             nl = 0;
  390.         }
  391.     }
  392.     if (!nl)
  393.         fprintf(fp, "\n");
  394. }
  395. #endif
  396.  
  397. /* Modify or displace interface trace flags */
  398. int
  399. dotrace(argc,argv,p)
  400. int argc;
  401. char *argv[];
  402. void *p;
  403. {
  404.     struct iface *ifp;
  405.     struct tracecmd *tp;
  406.  
  407.     if(argc < 2){
  408.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  409.             showtrace(ifp);
  410.         return 0;
  411.     }
  412.     if((ifp = if_lookup(argv[1])) == NULLIF){
  413.     tprintf(Badinterface,argv[1]);
  414.         return 1;
  415.     }
  416.     if(ifp->port){
  417.         tprintf("No trace on this interface - use master.\n");
  418.         return 1;
  419.     }
  420.     if(argc == 2){
  421.         showtrace(ifp);
  422.         return 0;
  423.     }
  424.     /* MODIFY THIS TO HANDLE MULTIPLE OPTIONS */
  425.     if(argc >= 3){
  426.         for(tp = Tracecmd;tp->name != NULLCHAR;tp++)
  427.             if(strncmp(tp->name,argv[2],strlen(argv[2])) == 0)
  428.                 break;
  429.         if(tp->name != NULLCHAR)
  430.             ifp->trace = (ifp->trace & ~tp->mask) | tp->val;
  431.         else
  432.             ifp->trace = htoi(argv[2]);
  433.     }
  434.     /* Always default to stdout unless trace file is given */
  435.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  436.         fclose(ifp->trfp);
  437.     ifp->trfp = stdout;
  438.     if(ifp->trfile != NULLCHAR)
  439.         free(ifp->trfile);
  440.     ifp->trfile = NULLCHAR;
  441.  
  442.     if(argc >= 4){
  443.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  444.             tprintf("Can't write to %s\n",argv[3]);
  445.             ifp->trfp = stdout;
  446.         } else {
  447.             ifp->trfile = strdup(argv[3]);
  448.         }
  449.     }
  450.     showtrace(ifp);
  451.     return 0;
  452. }
  453. /* Display the trace flags for a particular interface */
  454. static void
  455. showtrace(ifp)
  456. register struct iface *ifp;
  457. {
  458.     if(ifp == NULLIF)
  459.         return;
  460.     tprintf("%s:",ifp->name);
  461.     if(ifp->port){
  462.         tprintf(" trace on master interface only.\n");
  463.         return;
  464.     }
  465.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  466.         if(ifp->trace & IF_TRACE_IN)
  467.             tprintf(" input");
  468.         if(ifp->trace & IF_TRACE_OUT)
  469.             tprintf(" output");
  470.  
  471.         if(ifp->trace & IF_TRACE_NOBC)
  472.             tprintf(" - no broadcasts");
  473.  
  474. #ifdef MONITOR
  475.         if ((ifp->trace & IF_MONITOR) == IF_MONITOR)
  476.             tprintf(" (Monitoring)");
  477.         else
  478. #endif
  479.         if(ifp->trace & IF_TRACE_HEX)
  480.             tprintf(" (Hex/ASCII dump)");
  481.         else if(ifp->trace & IF_TRACE_ASCII)
  482.             tprintf(" (ASCII dump)");
  483.         else
  484.             tprintf(" (headers only)");
  485.  
  486.         if(ifp->trace & IF_TRACE_RAW)
  487.             tprintf(" Raw output");
  488.  
  489.         if(ifp->trfile != NULLCHAR)
  490.             tprintf(" trace file: %s",ifp->trfile);
  491.         tprintf("\n");
  492.     } else
  493.         tprintf(" tracing off\n");
  494. }
  495.  
  496. /* shut down all trace files */
  497. void
  498. shuttrace()
  499. {
  500.     struct iface *ifp;
  501.  
  502.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  503.         if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  504.             fclose(ifp->trfp);
  505.         if(ifp->trfile != NULLCHAR)
  506.             free(ifp->trfile);
  507.         ifp->trfile = NULLCHAR;
  508.         ifp->trfp = NULLFILE;
  509.     }
  510. }
  511.  
  512. /* Log messages of the form
  513.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  514.  */
  515. #if     defined(ANSIPROTO)
  516. void
  517. trace_log(struct iface *ifp,char *fmt, ...)
  518. {
  519.     static char buf[2048];
  520.     va_list ap;
  521.     char *cp;
  522.     long t;
  523.  
  524.     if(ifp->trfp == NULLFILE)
  525.         return;
  526.  
  527.     time(&t);
  528.     cp = ctime(&t);
  529.     rip(cp);
  530.     fprintf(ifp->trfp,"%s",cp);
  531.  
  532.     fprintf(ifp->trfp," - ");
  533.     va_start(ap,fmt);
  534.     vsprintf(buf,fmt,ap);
  535.     va_end(ap);
  536.     fprintf(ifp->trfp,"%s\n",buf);
  537. }
  538. #else
  539. /*VARARGS2*/
  540. void
  541. trace_log(ifp,fmt,arg1,arg2,arg3,arg4,arg5)
  542. struct iface *ifp;
  543. char *fmt;
  544. int arg1,arg2,arg3,arg4,arg5;
  545. {
  546.     char *cp;
  547.     long t;
  548.  
  549.     if(ifp->trfp == NULLFILE)
  550.         return;
  551.  
  552.     time(&t);
  553.     cp = ctime(&t);
  554.     rip(cp);
  555.     fprintf(ifp->trfp,"%s",cp);
  556.  
  557.     fprintf(ifp->trfp," - ");
  558.     fprintf(ifp->trfp,fmt,arg1,arg2,arg3,arg4,arg5);
  559.     fprintf(ifp->trfp,"\n");
  560. }
  561. #endif
  562.  
  563.  
  564. #endif /*TRACE*/
  565.